package com.property.demo.service.impl;

import com.property.demo.model.Owner;
import com.property.demo.model.Parking;
import com.property.demo.model.ParkingUsage;
import com.property.demo.model.Vehicle;
import com.property.demo.repository.OwnerRepository;
import com.property.demo.repository.ParkingRepository;
import com.property.demo.repository.ParkingUsageRepository;
import com.property.demo.repository.VehicleRepository;
import com.property.demo.service.ParkingUsageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class ParkingUsageServiceImpl implements ParkingUsageService {

    private static final Logger logger = LoggerFactory.getLogger(ParkingUsageServiceImpl.class);

    @Autowired
    private ParkingUsageRepository parkingUsageRepository;

    @Autowired
    private ParkingRepository parkingRepository;

    @Autowired
    private OwnerRepository ownerRepository;

    @Autowired
    private VehicleRepository vehicleRepository;

    @Override
    public List<ParkingUsage> findAll() {
        return parkingUsageRepository.findAll();
    }

    @Override
    public Page<ParkingUsage> findAll(Pageable pageable) {
        return parkingUsageRepository.findAll(pageable);
    }

    @Override
    public ParkingUsage findById(Long id) {
        return parkingUsageRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("ParkingUsage not found with id: " + id));
    }

    @Override
    @Transactional
    public ParkingUsage save(ParkingUsage parkingUsage) {
        validateParkingUsage(parkingUsage);
        
        // 确保usageType有默认值
        if (parkingUsage.getUsageType() == null) {
            parkingUsage.setUsageType(1); // 默认为租用
        }
        
        // 设置车位状态为已使用
        Parking parking = parkingUsage.getParking();
        parking.setStatus("已使用");
        parkingRepository.save(parking);
        
        return parkingUsageRepository.save(parkingUsage);
    }

    @Override
    @Transactional
    public ParkingUsage update(Long id, ParkingUsage parkingUsageDetails) {
        ParkingUsage existingParkingUsage = findById(id);
        
        // 确保usageType有默认值
        if (parkingUsageDetails.getUsageType() == null) {
            parkingUsageDetails.setUsageType(1); // 默认为租用
        }
        
        // 如果车位发生变化，需要更新原车位和新车位的状态
        if (parkingUsageDetails.getParking() != null && 
            !existingParkingUsage.getParking().getId().equals(parkingUsageDetails.getParking().getId())) {
            
            // 将原车位状态设置为空闲
            Parking oldParking = existingParkingUsage.getParking();
            oldParking.setStatus("空闲");
            parkingRepository.save(oldParking);
            
            // 将新车位状态设置为已使用
            Parking newParking = parkingRepository.findById(parkingUsageDetails.getParking().getId())
                    .orElseThrow(() -> new EntityNotFoundException("Parking not found with id: " + parkingUsageDetails.getParking().getId()));
            newParking.setStatus("已使用");
            parkingRepository.save(newParking);
            
            existingParkingUsage.setParking(newParking);
        }
        
        // 更新业主信息
        if (parkingUsageDetails.getOwner() != null) {
            Owner owner = ownerRepository.findById(parkingUsageDetails.getOwner().getId())
                    .orElseThrow(() -> new EntityNotFoundException("Owner not found with id: " + parkingUsageDetails.getOwner().getId()));
            existingParkingUsage.setOwner(owner);
        }
        
        // 更新车辆信息
        if (parkingUsageDetails.getVehicle() != null) {
            Vehicle vehicle = vehicleRepository.findById(parkingUsageDetails.getVehicle().getId())
                    .orElseThrow(() -> new EntityNotFoundException("Vehicle not found with id: " + parkingUsageDetails.getVehicle().getId()));
            existingParkingUsage.setVehicle(vehicle);
        }
        
        // 更新其他字段
        existingParkingUsage.setUsageType(parkingUsageDetails.getUsageType());
        existingParkingUsage.setStartDate(parkingUsageDetails.getStartDate());
        existingParkingUsage.setEndDate(parkingUsageDetails.getEndDate());
        existingParkingUsage.setFee(parkingUsageDetails.getFee());
        existingParkingUsage.setPaymentStatus(parkingUsageDetails.getPaymentStatus());
        existingParkingUsage.setRemarks(parkingUsageDetails.getRemarks());
        
        return parkingUsageRepository.save(existingParkingUsage);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        ParkingUsage parkingUsage = findById(id);
        
        // 删除记录前，将车位状态恢复为空闲
        if (parkingUsage.getParking() != null) {
            Parking parking = parkingUsage.getParking();
            parking.setStatus("空闲");
            parkingRepository.save(parking);
        }
        
        parkingUsageRepository.delete(parkingUsage);
    }

    @Override
    public List<ParkingUsage> findByCommunityId(Long communityId) {
        return parkingUsageRepository.findByParking_Community_Id(communityId);
    }

    @Override
    public Page<ParkingUsage> findByCommunityId(Long communityId, Pageable pageable) {
        return parkingUsageRepository.findByParking_Community_Id(communityId, pageable);
    }

    @Override
    public List<ParkingUsage> findByParkingId(Long parkingId) {
        return parkingUsageRepository.findByParkingId(parkingId);
    }

    @Override
    public List<ParkingUsage> findByOwnerId(Long ownerId) {
        return parkingUsageRepository.findByOwnerId(ownerId);
    }

    @Override
    public List<ParkingUsage> findByVehicleId(Long vehicleId) {
        return parkingUsageRepository.findByVehicleId(vehicleId);
    }

    @Override
    public List<ParkingUsage> findByOwnerName(String ownerName) {
        return parkingUsageRepository.findByOwner_NameContaining(ownerName);
    }

    @Override
    public List<ParkingUsage> findByLicensePlate(String licensePlate) {
        return parkingUsageRepository.findByVehicle_LicensePlateContaining(licensePlate);
    }

    @Override
    public List<ParkingUsage> findByPaymentStatus(String paymentStatus) {
        return parkingUsageRepository.findByPaymentStatus(paymentStatus);
    }

    @Override
    public List<ParkingUsage> findByUsageType(Integer usageType) {
        return parkingUsageRepository.findByUsageType(usageType);
    }

    @Override
    public List<ParkingUsage> findByCommunityIdAndUsageType(Long communityId, Integer usageType) {
        return parkingUsageRepository.findByParking_Community_IdAndUsageType(communityId, usageType);
    }

    @Override
    public List<ParkingUsage> findByCommunityIdAndPaymentStatus(Long communityId, String paymentStatus) {
        return parkingUsageRepository.findByParking_Community_IdAndPaymentStatus(communityId, paymentStatus);
    }

    @Override
    public List<ParkingUsage> search(Map<String, Object> params) {
        Specification<ParkingUsage> spec = buildSpecification(params);
        return parkingUsageRepository.findAll(spec);
    }

    @Override
    public Page<ParkingUsage> search(Map<String, Object> params, Pageable pageable) {
        Specification<ParkingUsage> spec = buildSpecification(params);
        return parkingUsageRepository.findAll(spec, pageable);
    }
    
    // 创建查询规范
    private Specification<ParkingUsage> buildSpecification(Map<String, Object> params) {
        return (root, query, builder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 小区ID
            if (params.containsKey("communityId")) {
                predicates.add(builder.equal(root.get("parking").get("community").get("id"), params.get("communityId")));
            }
            
            // 车位ID
            if (params.containsKey("parkingId")) {
                predicates.add(builder.equal(root.get("parking").get("id"), params.get("parkingId")));
            }
            
            // 业主ID
            if (params.containsKey("ownerId")) {
                predicates.add(builder.equal(root.get("owner").get("id"), params.get("ownerId")));
            }
            
            // 业主姓名模糊查询
            if (params.containsKey("ownerName")) {
                predicates.add(builder.like(root.get("owner").get("name"), 
                        "%" + params.get("ownerName") + "%"));
            }
            
            // 车牌号模糊查询
            if (params.containsKey("licensePlate")) {
                predicates.add(builder.like(root.get("vehicle").get("licensePlate"), 
                        "%" + params.get("licensePlate") + "%"));
            }
            
            // 使用类型
            if (params.containsKey("usageType")) {
                Object usageTypeObj = params.get("usageType");
                Integer usageTypeInt;
                
                if (usageTypeObj instanceof String) {
                    usageTypeInt = convertUsageTypeToInt((String) usageTypeObj);
                } else if (usageTypeObj instanceof Integer) {
                    usageTypeInt = (Integer) usageTypeObj;
                } else {
                    usageTypeInt = 1; // 默认为租用
                }
                
                predicates.add(builder.equal(root.get("usageType"), usageTypeInt));
            }
            
            // 支付状态
            if (params.containsKey("paymentStatus")) {
                predicates.add(builder.equal(root.get("paymentStatus"), params.get("paymentStatus")));
            }
            
            return predicates.isEmpty() ? null : builder.and(predicates.toArray(new Predicate[0]));
        };
    }
    
    // 验证ParkingUsage对象的必要字段
    private void validateParkingUsage(ParkingUsage parkingUsage) {
        if (parkingUsage.getParking() == null || parkingUsage.getParking().getId() == null) {
            throw new IllegalArgumentException("Parking is required");
        }
        
        if (parkingUsage.getOwner() == null || parkingUsage.getOwner().getId() == null) {
            throw new IllegalArgumentException("Owner is required");
        }
        
        // 验证车位是否存在
        Parking parking = parkingRepository.findById(parkingUsage.getParking().getId())
                .orElseThrow(() -> new EntityNotFoundException("Parking not found with id: " + parkingUsage.getParking().getId()));
        
        // 检查车位是否已被占用
        if ("已使用".equals(parking.getStatus())) {
            throw new IllegalStateException("Parking is already in use");
        }
        
        // 验证业主是否存在
        Owner owner = ownerRepository.findById(parkingUsage.getOwner().getId())
                .orElseThrow(() -> new EntityNotFoundException("Owner not found with id: " + parkingUsage.getOwner().getId()));
        
        // 验证车辆是否存在(如果提供)
        if (parkingUsage.getVehicle() != null && parkingUsage.getVehicle().getId() != null) {
            Vehicle vehicle = vehicleRepository.findById(parkingUsage.getVehicle().getId())
                    .orElseThrow(() -> new EntityNotFoundException("Vehicle not found with id: " + parkingUsage.getVehicle().getId()));
            
            // 检查车辆是否属于当前业主
            if (!vehicle.getOwner().getId().equals(owner.getId())) {
                throw new IllegalArgumentException("Vehicle does not belong to the specified owner");
            }
            
            parkingUsage.setVehicle(vehicle);
        }
        
        parkingUsage.setParking(parking);
        parkingUsage.setOwner(owner);
    }

    // 添加一个辅助方法，将字符串类型的使用类型转换为整数
    private Integer convertUsageTypeToInt(String usageType) {
        if (usageType == null) return null;
        
        switch (usageType) {
            case "租用":
                return 1;
            case "购买":
                return 2;
            case "临时":
                return 3;
            default:
                try {
                    return Integer.parseInt(usageType);
                } catch (NumberFormatException e) {
                    return 1; // 默认为租用
                }
        }
    }
}